package com.jiangsong.batch.abst;

import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;

import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;

public abstract class AbstractSyncManagerSupport<E, C> {

    private final ThreadLocal<Stack<E>> executionHolder = new ThreadLocal<>();

    private final Map<E, C> contextMap = new ConcurrentHashMap<>();

    public void register(E execution) {
        if (null == execution) {
            return;
        }

        this.getCurrentThreadStack().push(execution);

        C context;
        synchronized (this.contextMap) {
            context = this.contextMap.get(execution);
            if (null == context) {
                context = this.newContext(execution, null);
                this.contextMap.put(execution, context);
            }
        }

    }

    public void release() {
        this.executionHolder.remove();
    }

    public C getContext() {
        if (this.getCurrentThreadStack().isEmpty()) {
            return null;
        }
        synchronized (this.contextMap) {
            return this.contextMap.get(this.getCurrentThreadStack().peek());
        }
    }

    public Stack<E> getCurrentThreadStack() {
        if (this.executionHolder.get() == null) {
            this.executionHolder.set(new Stack<>());
        }
        return this.executionHolder.get();
    }


    protected abstract C newContext(E execution, BatchPropertyContext batchPropertyContext);
}
